﻿using System.Globalization;

namespace Sgr.Utilities
{
    public static class DateTimeHelper
    {
        /// <summary>
        /// 尝试将 ISO 8601 格式的日期时间字符串解析为 UTC 的 DateTime 对象。
        /// 要求输入必须包含时区信息（如 'Z'、'+08:00' 或 '-05:00'）。
        /// </summary>
        /// <param name="value">ISO 8601 日期时间字符串</param>
        /// <param name="result">解析成功的 UTC DateTime（Kind = Utc）</param>
        /// <returns>如果成功解析则为 true；否则为 false</returns>
        public static bool TryParseToUtc(string? value, out DateTime result)
        {
            result = default;

            if (string.IsNullOrEmpty(value))
                return false;

            // 尝试解析为 DateTimeOffset
            if (!DateTimeOffset.TryParse(
                    value,
                    CultureInfo.InvariantCulture,
                    DateTimeStyles.None,
                    out var dto))
            {
                return false;
            }

            // 检查是否包含时区信息（防止被当作本地时间）
            var trimmed = value.AsSpan().Trim();

            // 简化时区检测逻辑：支持末尾 'Z' 或 "+HH:MM"/"-HH:MM"
            bool hasTimeZone = trimmed.EndsWith("Z", StringComparison.OrdinalIgnoreCase) || EndsWithOffset(trimmed);

            if (!hasTimeZone)
            {
                // 不包含明确时区信息，拒绝解析（避免歧义）
                return false;
            }

            result = dto.UtcDateTime;
            return true;
        }

        private static bool EndsWithOffset(ReadOnlySpan<char> span)
        {
            // 形如 +08:00 / -05:30 共 6 字符
            if (span.Length < 6) return false;
            var tz = span[^6..]; // 最后6个字符
            return (tz[0] == '+' || tz[0] == '-') &&
                   tz[3] == ':' &&
                   char.IsDigit(tz[1]) &&
                   char.IsDigit(tz[2]) &&
                   char.IsDigit(tz[4]) &&
                   char.IsDigit(tz[5]);
        }

        /// <summary>
        /// 将 ISO 8601 格式的日期时间字符串解析为 UTC 的 DateTime 对象。
        /// 要求输入必须包含时区信息（如 'Z'、'+08:00' 或 '-05:00'）。
        /// </summary>
        /// <param name="value">ISO 8601 日期时间字符串</param>
        /// <returns>UTC 时间的 DateTime 对象（Kind = Utc）</returns>
        /// <exception cref="ArgumentException">当 value 为 null 或空</exception>
        /// <exception cref="FormatException">当格式无效或缺少时区信息</exception>
        public static DateTime ParseToUtc(string value)
        {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentException("值不能为空或 null。", nameof(value));

            if (TryParseToUtc(value, out var result))
                return result;

            throw new FormatException($"无法解析为有效的 ISO 8601 日期时间格式: {value}");
        }

        /// <summary>
        /// 将Unix时间戳（秒）转换为DateTimeOffset
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        public static DateTimeOffset TimestampSecondsToDateTimeOffset(long timestamp)
        {
            return DateTimeOffset.FromUnixTimeSeconds(timestamp);
        }

        /// <summary>
        /// 将Unix时间戳（秒）转换为DateTime
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        public static DateTime TimestampSecondsToDateTime(long timestamp)
        {
            return TimestampSecondsToDateTimeOffset(timestamp).UtcDateTime;
        }

        /// <summary>
        /// 获取当前UTC时间的Unix时间戳（秒）
        /// </summary>
        /// <returns></returns>
        public static long TimestampSeconds()
        {
            return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        }

        /// <summary>
        /// 获取指定过期时间的Unix时间戳（秒）
        /// </summary>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public static long TimestampSeconds(TimeSpan expiry)
        {
            return DateTimeOffset.UtcNow.Add(expiry).ToUnixTimeSeconds();
        }
    }
}